

#include "owntypes.h"
#include "license_basic.h"
#include "files2.h"
#include "stdio.h"

//#define LICENSE_CRC_PRINT


typedef void (SpecialExitFunctionPtr) (int32 ExitCode);	// funcptr is synonym for "pointer

#define S(x,i) (bf_S[i][x.w.byte##i])
#define bf_F(x) (((S(x,0) + S(x,1)) ^ S(x,2)) + S(x,3))
#define ROUND(a,b,n) (a.word ^= bf_F(b) ^ bf_P[n])

#define MAXKEYBYTES           56	/* 448 bits */
#define bf_N                  16
#define KEYBYTES              8

#define BUFSIZE               8192

union aword
{
	uint32 word;
	BYTE byte[4];
	struct
	{
		unsigned int byte3:8;
		unsigned int byte2:8;
		unsigned int byte1:8;
		unsigned int byte0:8;
	} w;
};

BYTE SearchSequence[10] = { 0xba, 0x20, 0x3a, 0xc6, 0x4b, 0xb9, 0x33, 0xab, 0x79, 0xdb };

uint32 crc32_table[256];

BYTE ProgramCRC[8] = { 0x73, 0x2a, 0x6d, 0x31, 0xb9, 0xc2, 0x5e, 0xb2 };
BYTE BlowFishCrc[8] = { 0x43, 0x9b, 0x78, 0x8b, 0x3a, 0x9a, 0xcc, 0xb7 };
BYTE ProgramCRC2[8] = { 0x7e, 0x4b, 0x1f, 0x12, 0xdf, 0x43, 0x25, 0x79 };
BYTE BlowFishCrc2[8] = { 0xaa, 0xd1, 0x00, 0xd7, 0xf1, 0x3c, 0xca, 0x29 };
uint32 ProgramSpecialCRC;
int32 ProgramSpecialCRCPosition;
int32 ProgramSpecialCRCPosition2;
int32 ProgramSpecialLength;
int32 CrcInit = 0;


SpecialExitFunctionPtr *SpecialExitFunction;


uint8 ScrambleBuf[BUFSIZE];

static uint32 bf_P[bf_N + 2];
static uint32 bf_S[4][256];

static uint32 bf_P_default[bf_N + 2] = {
	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
	0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
	0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
	0x9216d5d9, 0x8979fb1b,
};

static uint32 bf_S_default[4][256] = {
	{	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
		0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
		0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
		0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
		0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
		0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
		0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
		0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
		0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
		0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
		0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
		0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
		0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
		0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
		0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
		0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
		0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
		0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
		0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
		0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
		0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
		0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
		0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
		0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
		0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
		0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
		0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
		0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
		0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
		0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
		0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
		0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
		0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
		0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
		0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
		0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
		0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
		0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
		0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
		0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
		0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
		0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
		0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
		0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
		0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
		0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
		0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
		0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
		0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
		0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
		0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
		0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
		0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
		0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
		0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
		0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
		0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
		0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
		0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
		0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
		0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
		0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
		0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
		0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
	},
	{	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
		0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
		0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
		0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
		0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
		0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
		0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
		0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
		0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
		0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
		0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
		0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
		0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
		0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
		0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
		0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
		0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
		0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
		0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
		0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
		0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
		0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
		0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
		0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
		0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
		0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
		0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
		0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
		0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
		0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
		0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
		0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
		0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
		0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
		0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
		0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
		0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
		0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
		0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
		0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
		0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
		0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
		0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
		0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
		0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
		0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
		0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
		0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
		0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
		0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
		0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
		0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
		0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
		0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
		0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
		0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
		0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
		0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
		0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
		0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
		0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
		0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
		0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
		0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
	},
	{	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
		0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
		0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
		0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
		0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
		0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
		0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
		0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
		0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
		0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
		0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
		0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
		0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
		0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
		0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
		0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
		0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
		0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
		0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
		0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
		0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
		0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
		0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
		0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
		0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
		0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
		0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
		0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
		0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
		0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
		0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
		0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
		0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
		0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
		0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
		0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
		0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
		0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
		0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
		0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
		0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
		0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
		0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
		0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
		0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
		0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
		0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
		0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
		0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
		0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
		0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
		0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
		0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
		0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
		0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
		0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
		0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
		0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
		0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
		0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
		0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
		0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
		0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
		0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
	},
	{	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
		0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
		0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
		0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
		0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
		0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
		0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
		0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
		0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
		0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
		0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
		0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
		0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
		0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
		0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
		0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
		0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
		0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
		0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
		0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
		0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
		0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
		0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
		0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
		0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
		0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
		0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
		0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
		0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
		0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
		0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
		0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
		0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
		0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
		0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
		0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
		0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
		0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
		0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
		0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
		0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
		0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
		0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
		0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
		0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
		0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
		0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
		0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
		0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
		0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
		0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
		0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
		0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
		0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
		0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
		0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
		0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
		0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
		0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
		0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
		0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
		0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
		0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
		0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
	}
};

// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************

void Blowfish_encipher(uint32 * xl, uint32 * xr)
{
	union aword Xl;
	union aword Xr;

	Xl.word = *xl;
	Xr.word = *xr;

	Xl.word ^= bf_P[0];
	ROUND(Xr, Xl, 1);
	ROUND(Xl, Xr, 2);
	ROUND(Xr, Xl, 3);
	ROUND(Xl, Xr, 4);
	ROUND(Xr, Xl, 5);
	ROUND(Xl, Xr, 6);
	ROUND(Xr, Xl, 7);
	ROUND(Xl, Xr, 8);
	ROUND(Xr, Xl, 9);
	ROUND(Xl, Xr, 10);
	ROUND(Xr, Xl, 11);
	ROUND(Xl, Xr, 12);
	ROUND(Xr, Xl, 13);
	ROUND(Xl, Xr, 14);
	ROUND(Xr, Xl, 15);
	ROUND(Xl, Xr, 16);
	Xr.word ^= bf_P[17];

	*xr = Xl.word;
	*xl = Xr.word;
}

// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************

void Blowfish_decipher(uint32 * xl, uint32 * xr)
{
	union aword Xl;
	union aword Xr;

	Xl.word = *xl;
	Xr.word = *xr;

	Xl.word ^= bf_P[17];
	ROUND(Xr, Xl, 16);
	ROUND(Xl, Xr, 15);
	ROUND(Xr, Xl, 14);
	ROUND(Xl, Xr, 13);
	ROUND(Xr, Xl, 12);
	ROUND(Xl, Xr, 11);
	ROUND(Xr, Xl, 10);
	ROUND(Xl, Xr, 9);
	ROUND(Xr, Xl, 8);
	ROUND(Xl, Xr, 7);
	ROUND(Xr, Xl, 6);
	ROUND(Xl, Xr, 5);
	ROUND(Xr, Xl, 4);
	ROUND(Xl, Xr, 3);
	ROUND(Xr, Xl, 2);
	ROUND(Xl, Xr, 1);
	Xr.word ^= bf_P[0];

	*xl = Xr.word;
	*xr = Xl.word;
}

// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************

/* FIXME: Blowfish_Initialize() ??? */
int32 InitializeBlowfish(uint8 * Key)
{
	int32 i;
	int32 j;
	uint32 data;
	uint32 datal;
	uint32 datar;
	union aword temp;

//  fprintf (stderr, "0x%x 0x%x ", bf_P[0], bf_P[1]); DEBUG */
//  fprintf (stderr, "%d %d\n", bf_P[0], bf_P[1]);  DEBUG

	int32 keybytes;

	memmove(&bf_P, &bf_P_default, sizeof(bf_P_default));
	memmove(&bf_S, &bf_S_default, sizeof(bf_S_default));

	keybytes = (int32) strlen((LPSTR) Key);

	if (keybytes > MAXKEYBYTES)
		return -1;

	j = 0;

	for (i = 0; i < bf_N + 2; ++i)
	{
		temp.word = 0;
		temp.w.byte0 = Key[j];
		temp.w.byte1 = Key[(j + 1) % keybytes];
		temp.w.byte2 = Key[(j + 2) % keybytes];
		temp.w.byte3 = Key[(j + 3) % keybytes];
		data = temp.word;
		bf_P[i] = bf_P[i] ^ data;
		j = (j + 4) % keybytes;
	}

	datal = 0x00000000;
	datar = 0x00000000;

	for (i = 0; i < bf_N + 2; i += 2)
	{
		Blowfish_encipher(&datal, &datar);

		bf_P[i] = datal;
		bf_P[i + 1] = datar;
	}

	for (i = 0; i < 4; ++i)
	{
		for (j = 0; j < 256; j += 2)
		{
			Blowfish_decipher(&datal, &datar);
			bf_S[i][j] = datal;
			bf_S[i][j + 1] = datar;
		}
	}

	return 0;
}

// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************

int32 EncryptBlock(uint8 * Block, int32 BlockSize)
{
	int32 tel;
	uint32 *Left, *Right;

	for (tel = 0; tel < (BlockSize >> 3); tel++)
	{
		Left = (uint32 *) & Block[tel * 8];
		Right = (uint32 *) & Block[tel * 8 + 4];
		Blowfish_encipher(Left, Right);
	}

	return 0;
}

// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************

int32 DecryptBlock(uint8 * Block, int32 BlockSize)
{
	int32 tel;
	uint32 *Left, *Right;

	for (tel = 0; tel < (BlockSize >> 3); tel++)
	{
		Left = (uint32 *) & Block[tel * 8];
		Right = (uint32 *) & Block[tel * 8 + 4];
		Blowfish_decipher(Left, Right);
	}

	return 0;
}


// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************

// Reflection is a requirement for the official CRC-32 standard.
// You can create CRCs without it, but they won't conform to the standard.
uint32 Reflect(uint32 ref, char ch)
{	// Used only by Init_CRC32_Table()

	uint32 value = 0;
	int32 i;

	// Swap bit 0 for bit 7
	// bit 1 for bit 6, etc.
	for (i = 1; i < (ch + 1); i++)
	{
		if (ref & 1)
			value |= 1 << (ch - i);

		ref >>= 1;
	}

	return value;
}


// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************

// Call this function only once to initialize the CRC table.
void Init_CRC32_Table()
{	// Called by OnInitDialog()

	// This is the official polynomial used by CRC-32
	// in PKZip, WinZip and Ethernet.
	int32 i, j;
	uint32 ulPolynomial = 0x04c11db7;

	// 256 values representing ASCII character codes.
	for (i = 0; i <= 0xFF; i++)
	{
		crc32_table[i] = Reflect(i, 8) << 24;

		for (j = 0; j < 8; j++)
			crc32_table[i] = (crc32_table[i] << 1) ^ (crc32_table[i] & (1 << 31) ? ulPolynomial : 0);

		crc32_table[i] = Reflect(crc32_table[i], 32);
	}
}

// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************

#ifdef GCC_COMP

#pragma GCC push_options
#pragma GCC optimize ("O0")

#endif

int32 GetCRC()
{
#ifndef X64
#ifndef GCC_COMP
	__asm
	{
		mov edx, 0x4bc63a20 mov ecx, 0xdb79ab33 mov ecx, 0xae909198 mov ebx, 0x8bdf08c9 mov eax,
		0xb90d65cf mov DWORD PTR[ProgramCRC], ebx mov DWORD PTR[ProgramCRC + 4], eax}
#else
	__asm__("movl   $0x4bc63a20,%%edx\n\t" "movl   $0xdb79ab33,%%ecx\n\t" "movl   $0xae909198,%%ecx\n\t" "movl   $0x8bdf08c9,%%ebx\n\t" "movl   $0xb90d65cf,%%eax\n\t" "movl   %%ebx,(_ProgramCRC)\n\t" "movl   %%eax,(_ProgramCRC+4)\n\t":
	        :
	        :"eax", "ebx", "ecx", "edx");
	/*

	*/

#endif
#endif

	if (CrcInit == 0)
	{
		Init_CRC32_Table();
		CrcInit++;
	}

	/*
	0040245C BA 20 3A C6 4B       mov         edx,4BC63A20h
	00402461 B9 33 AB 79 DB       mov         ecx,0DB79AB33h
	00402466 B9 98 91 90 AE       mov         ecx,0AE909198h
	0040246B BB C9 08 DF 8B       mov         ebx,8BDF08C9h
	00402470 B8 CF 65 0D B9       mov         eax,0B90D65CFh

	00402466 = SequenceIndex

	  FileSeek(fp,SequenceIndex+1);
	  FileWrite(fp,BlowFishCrc,4,&result);
	  FileSeek(fp,SequenceIndex+6);
	  FileWrite(fp,&BlowFishCrc[4],4,&result);

	*/
	return 0;
}


// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************

int32 GetCRC2()
{
#ifndef X64
#ifndef GCC_COMP
	__asm
	{
		mov edx, 0xb8e1afed mov ecx, 0x6a267e96 mov ebx, 0xba7c9045 mov eax, 0xf12c7f99 mov ecx, 0xf0255dc1 mov edx,
		0x3ebaefc9 mov DWORD PTR[ProgramSpecialCRC], ebx mov DWORD PTR[ProgramSpecialCRCPosition],
		eax mov DWORD PTR[ProgramSpecialCRCPosition2], ecx mov DWORD PTR[ProgramSpecialLength], edx}
#else
	__asm__("movl   $0xb8e1afed,%%edx\n\t" "movl   $0x6a267e96,%%ecx\n\t" "movl   $0xba7c9045,%%ebx\n\t" "movl   $0xf12c7f99,%%eax\n\t" "movl   $0xf0255dc1,%%ecx\n\t" "movl   $0x3ebaefc9,%%edx\n\t" "movl   %%ebx,(_ProgramSpecialCRC)\n\t" "movl   %%eax,(_ProgramSpecialCRCPosition)\n\t" "movl   %%ecx,(_ProgramSpecialCRCPosition2)\n\t" "movl   %%edx,(_ProgramSpecialLength)\n\t":
	        :
	        :"eax", "ebx", "ecx", "edx");
#endif
#endif

	if (CrcInit == 0)
	{
		Init_CRC32_Table();
		CrcInit++;
	}

	SpecialExitFunction = (SpecialExitFunctionPtr *) & ExitProcess;

	/*
	0040245C BA ED AF E1 B8       mov         edx,0B8E1AFEDh
	00402461 B9 96 7E 26 6A       mov         ecx,6A267E96h
	00402466 BB 45 90 7C BA       mov         ebx,0BA7C9045h
	0040246B B8 99 7F 2C F1       mov         eax,0F12C7F99h
	0040246F B9 C1 5D 25 F0       mov         ecx,0F0255DC1h
	00402474 BA C9 EF BA 3E       mov         edx,3EBAEFC9h

	00402466 = SequenceIndex2

	  FileSeek(fp,SequenceIndex2+1);
	  FileWrite(fp,&crc2,4,&result);
	  FileSeek(fp,SequenceIndex2+6);
	  FileWrite(fp,&SequenceIndex2,4,&result);
	  FileSeek(fp,SequenceIndex2+11);
	  FileWrite(fp,&ProgramLength,4,&result);

	*/
	return 0;
}

#ifdef GCC_COMP

#pragma GCC pop_options

#endif

// ****************************************************************************************************
// ****************************************************************************************************
// ****************************************************************************************************
// ****************************************************************************************************

void SpecialExit()
{
//  return;
#ifndef VC80
#ifndef GCC_COMP
	_asm
	{

		mov ecx, 0x400 xor eax, eax add ebp, 4 loop1: mov[ebp], eax add ebp, 4 loop loop1}
#endif
#endif
	SpecialExitFunction(0);
}

// ****************************************************************************************************
// ****************************************************************************************************
// ****************************************************************************************************
// ****************************************************************************************************

void ScrambleMessage(LPSTR SrcString, LPSTR DestVar)
{
	uint8 SrcCode[MAX_LENGTH_STRING];
	char str[MAX_LENGTH_STRING], str2[MAX_LENGTH_STRING];
	int32 length, length2, tel;

	memset(&SrcCode, 0, sizeof(SrcCode));
	strcpy((LPSTR) SrcCode, SrcString);

	length = (int32) strlen(SrcString);
	length2 = (length + 7) & ~7;

	InitializeBlowfish((uint8 *) CRC_PASSWORD);
	EncryptBlock((uint8 *) & SrcCode, 128);

	length2 = 128;
	tel = 0;

	while (tel < length2)
	{
		if (tel == 0)
		{
			sprintf(str, "uint8 %s[128]={\n", DestVar);
			OutputDebugString(str);
		}

		if ((tel > 0) && ((tel % 8) == 0))
		{
			strcat(str, "\n");
			OutputDebugString(str);
		}

		if ((tel % 8) == 0)
			strcpy(str, "       ");

		sprintf(str2, "0x%02X", SrcCode[tel]);
		strcat(str, str2);

		if (tel < length2 - 1)
			strcat(str, ",");
		else
		{
			strcat(str, "};\n");
			OutputDebugString(str);
		}

		tel++;
	}

//  memmove(DestCode,SrcCode,128);
//  InitializeBlowfish(CRC_PASSWORD);
//  DecryptBlock(DestCode,128,CRC_PASSWORD);
}

// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************

void DeScrambleMessage(uint8 * Src, uint8 * Dest)
{
	memmove(Dest, Src, 128);
	InitializeBlowfish((uint8 *) CRC_PASSWORD);
	DecryptBlock(Dest, 128);
}


// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************

int32 CheckCRC(LPSTR FileName, int32 * FileCheck1)
{
#define  BUF_SIZE   16384
	int32 result, len, index, FileP, SequenceIndex, res;
	uint8 buf[BUF_SIZE + 1024], FirstByte;
	int32 fp;
	boolean Found;
#ifdef LICENSE_CRC_PRINT
	char str[200];
#endif
	uint32 crc = 0xffffffff;

	SequenceIndex = 0;
	Init_CRC32_Table();
//  MessageBox(NULL,FileName,"Executable",MB_APPLMODAL|MB_OK);

	if ((fp = FileOpenReadOnlyUTF8(FileName)) <= 0)
	{
		MessageBox(NULL, FileName, "Open executable failed", MB_APPLMODAL | MB_OK);
		Beep(1000, 200);
		return 0;
	}

	FirstByte = SearchSequence[0];
	FileP = 0;
	Found = FALSE;
	result = 1;

	while ((!Found) && (result > 0))
	{
		FileRead(fp, buf, BUF_SIZE, &result);

		if (result > 0)
		{
			index = 0;

			while ((!Found) && (index < result - 12))
			{
				if (buf[index] == FirstByte)
				{
					if (memcmp(&buf[index], SearchSequence, sizeof(SearchSequence)) == 0)
					{
						Found = TRUE;
						SequenceIndex = FileP + index + 10;
					}
				}

				index++;
			}

			FileP += min(BUF_SIZE, result);
			FileSeek(fp, FileP);
		}
	}

	/*
	  if (Found) {
	    MessageBox(NULL,"Found sequence","Message",MB_APPLMODAL|MB_OK);
	  }
	*/
	*FileCheck1 = 0;
	FileSeek(fp, 0);
	FileP = 0;
	result = 1;

	while (result > 0)
	{
		FileRead(fp, buf, BUF_SIZE, &result);

		if (result > 0)
		{
			len = result;
			index = 0;

			while (len--)
			{
				if ((FileP + index < SequenceIndex) || (FileP + index >= SequenceIndex + 15))
					crc = (crc >> 8) ^ crc32_table[(crc & 0xFF) ^ buf[index]];
				else
					res = 1;

				index++;
			}
		}

		FileP += min(BUF_SIZE, result);
		FileSeek(fp, FileP);
	}

	FileClose(fp);
	crc ^= 0xffffffff;

	InitializeBlowfish((uint8 *) CRC_PASSWORD);
	memmove(BlowFishCrc, &crc, 4);
	memmove(&BlowFishCrc[4], &crc, 4);
//  DecryptBlock(BlowFishCrc,8,CRC_PASSWORD);
	EncryptBlock(BlowFishCrc, 8);

	GetCRC();

#ifdef LICENSE_CRC_PRINT
	sprintf(str, "CRC check1 in file %08X,%08X  <---> Calculated crc %08X,%08X", *(uint32 *) & ProgramCRC[0],
	        *(uint32 *) & ProgramCRC[4], *(uint32 *) & BlowFishCrc[0], *(uint32 *) & BlowFishCrc[4]);
	MessageBox(NULL, str, "Message", MB_APPLMODAL | MB_OK);
#endif

	if (memcmp(ProgramCRC, BlowFishCrc, 8) == 0)
		return 1;

	return 0;
}

// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************


int32 CheckCRC2(LPSTR FileName)
{
#define  BUF_SIZE   16384
	int32 result, len, index, FileP, SequenceIndex, res;
	uint8 buf[BUF_SIZE + 1024], FirstByte;
	int32 fp;
	boolean Found;
#ifdef LICENSE_CRC_PRINT
	char str[200];
#endif
	uint32 crc = 0xffffffff;

	SequenceIndex = 0;
	Init_CRC32_Table();
//  MessageBox(VIEWPLOTWindow,EngraverExecutable,"",MB_APPLMODAL|MB_OK);

	if ((fp = FileOpenReadOnlyUTF8(FileName)) <= 0)
	{
//    Beep(1000,MAX_LENGTH_STRING);
		return 0;
	}

	FirstByte = SearchSequence[0];
	FileP = 0;
	Found = FALSE;
	result = 1;

	while ((!Found) && (result > 0))
	{
		FileRead(fp, buf, BUF_SIZE, &result);

		if (result > 0)
		{
			index = 0;

			while ((!Found) && (index < result - 12))
			{
				if (buf[index] == FirstByte)
				{
					if (memcmp(&buf[index], SearchSequence, sizeof(SearchSequence)) == 0)
					{
						Found = TRUE;
						SequenceIndex = FileP + index + 10;
					}
				}

				index++;
			}

			FileP += min(BUF_SIZE, result);
			FileSeek(fp, FileP);
		}
	}

	FileSeek(fp, 0);
	FileP = 0;
	result = 1;

	while (result > 0)
	{
		FileRead(fp, buf, BUF_SIZE, &result);

		if (result > 0)
		{
			len = result;
			index = 0;

			while (len--)
			{
				if ((FileP + index < SequenceIndex) || (FileP + index >= SequenceIndex + 15))
					crc = (crc >> 8) ^ crc32_table[(crc & 0xFF) ^ buf[index]];
				else
					res = 1;

				index++;
			}
		}

		FileP += min(BUF_SIZE, result);
		FileSeek(fp, FileP);
	}

//  GetCRC();
	memmove(&ProgramCRC2, &ProgramCRC, 8);
	FileClose(fp);
	crc ^= 0xffffffff;

	InitializeBlowfish((uint8 *) CRC_PASSWORD);
	memmove(BlowFishCrc2, &crc, 4);
	memmove(&BlowFishCrc2[4], &crc, 4);
//  DecryptBlock(BlowFishCrc2,8);
	EncryptBlock(BlowFishCrc2, 8);


#ifdef LICENSE_CRC_PRINT
	sprintf(str, "CRC check2 in file %08X,%08X  <---> Calculated crc %08X,%08X", *(uint32 *) & ProgramCRC2[0],
	        *(uint32 *) & ProgramCRC2[4], *(uint32 *) & BlowFishCrc2[0], *(uint32 *) & BlowFishCrc2[4]);
	MessageBox(NULL, str, "Message", MB_APPLMODAL | MB_OK);
#endif

	if (memcmp(ProgramCRC2, BlowFishCrc2, 8) == 0)
		return 1;

	return 0;
}


// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************

uint32 CalcCrcFile(LPSTR Filename)
{
#define  BUF_SIZE   16384
	int32 result, len, index;
	uint8 buf[BUF_SIZE + 1024];
	int32 fp;
	uint32 crc = 0xffffffff;

	Init_CRC32_Table();

	if ((fp = FileOpenReadOnlyUTF8(Filename)) <= 0)
	{
//    Beep(1000,MAX_LENGTH_STRING);
		return 0;
	}

	FileP = 0;
	result = 1;

	while (result > 0)
	{
		FileRead(fp, buf, BUF_SIZE, &result);

		if (result > 0)
		{
			len = result;
			index = 0;

			while (len--)
			{
				crc = (crc >> 8) ^ crc32_table[(crc & 0xFF) ^ buf[index]];
				index++;
			}
		}
	}

	FileClose(fp);
	return crc;
}

// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************

int32 ScrambleZipFile(LPSTR FileName, LPSTR NewFile, LPSTR PassWord)
{

	int32 tel, count, result, fp, fp2, res;
	uint32 *Left, *Right;
	char PassWord2[64];

	memset(&PassWord2, 0, sizeof(PassWord2));
	strcpy(PassWord2, PassWord);
	InitializeBlowfish((uint8 *) PassWord2);

	if ((fp2 = FileOpenWrite(NewFile)) <= 0)
		return -1;

	if ((fp = FileOpenReadOnlyUTF8(FileName)) <= 0)
		return -1;

	result = 1;

	while (result > 0)
	{
		memset(&ScrambleBuf, 0, BUFSIZE);
		FileRead(fp, &ScrambleBuf, BUFSIZE, &result);

		if (result > 0)
		{
			count = (result + 7) >> 3;

			for (tel = 0; tel < count; tel++)
			{
				Left = (uint32 *) & ScrambleBuf[tel * 8];
				Right = (uint32 *) & ScrambleBuf[tel * 8 + 4];
				Blowfish_encipher(Left, Right);
			}

			FileWrite(fp2, &ScrambleBuf, count * 8, &res);
		}
	}

	FileClose(fp);
	FileClose(fp2);
	return 0;
}

// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
// *******************************************************************************************************
